package net.wofly.finance.expense.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.transaction.Transactional;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import net.wofly.common.condition.Condition;
import net.wofly.common.condition.ConditionRelate;
import net.wofly.common.condition.ConditionUtil;
import net.wofly.common.condition.FilterCondition;
import net.wofly.common.condition.Operation;
import net.wofly.common.json.XiNiaoJSON;
import net.wofly.finance.expense.domain.ExpenseAccount;
import net.wofly.finance.expense.domain.ExpenseAccountAttachment;
import net.wofly.finance.expense.domain.ExpenseType;
import net.wofly.finance.expense.repository.ExpenseAccountRepository;
import net.wofly.finance.expense.service.IExpenseAccountAttachmentService;
import net.wofly.finance.expense.service.IExpenseAccountFlowService;
import net.wofly.finance.expense.service.IExpenseAccountService;
import net.wofly.finance.expense.service.IExpenseTypeService;
import net.wofly.finance.expense.util.ExpenseAccountStatus;
import net.wofly.framework.dao.PageWrapper;
import net.wofly.framework.util.Identities;
import net.wofly.framework.util.PageHelper;
import net.wofly.framework.util.ReturnBean;
import net.wofly.right.domain.Organization;
import net.wofly.right.domain.User;
import net.wofly.right.service.IOrganizationService;
import net.wofly.right.service.IUserService;

@Service("iExpenseAccountService")
@Transactional
public class ExpenseAccountServiceImpl implements IExpenseAccountService {
	
	@Autowired
	ExpenseAccountRepository expenseAccountRepository;
	
	@Autowired
	IExpenseAccountAttachmentService iExpenseAccountAttachmentService ;
	
	@Autowired
	IExpenseAccountFlowService iExpenseAccountFlowService;
	
	@Autowired
	IExpenseTypeService iExpenseTypeService ;
	
	@Autowired
	IUserService iUserService ;
	
	@Autowired
	IOrganizationService iOrganizationService ;
	
	@Override
	public ReturnBean<ExpenseAccount> saveExpenseAccount(ExpenseAccount expenseAccount) {
		expenseAccount.setExpenseAccountID(Identities.uuid2());
		expenseAccount.setExpenseAccountNO(getExpenseAccountNO());
		expenseAccount.setModifyDate(System.currentTimeMillis());
		expenseAccount.setAskTime(expenseAccount.getModifyDate());
		
		ReturnBean rtnBean = iExpenseAccountAttachmentService.save(expenseAccount);
		if (!rtnBean.getCode().equals(ReturnBean.CODE_SUCCESS)) {
			return new ReturnBean<>(9200022 , "保存报销申请单出错！") ;
		}
		
		User user = iUserService.findOne(expenseAccount.getAskUserID()) ;
		expenseAccount.setOrgID(user.getOrganizationID());
		
		return new ReturnBean<>(ReturnBean.CODE_SUCCESS , "保存报销申请单成功！" ,expenseAccountRepository.save(expenseAccount)) ;
	}
	
	@Override
	public ReturnBean<ExpenseAccount> updateExpenseAccount(ExpenseAccount expenseAccount) {
		ExpenseAccount dbExpenseAccount = expenseAccountRepository.findOne(expenseAccount.getExpenseAccountID()) ;
		
		expenseAccount.setExpenseAccountID(dbExpenseAccount.getExpenseAccountID());
		expenseAccount.setExpenseAccountNO(dbExpenseAccount.getExpenseAccountNO());
		expenseAccount.setModifyDate(System.currentTimeMillis());
		expenseAccount.setAskTime(expenseAccount.getModifyDate());
		
		ReturnBean rtnBean = iExpenseAccountAttachmentService.update(expenseAccount);
		if (!rtnBean.getCode().equals(ReturnBean.CODE_SUCCESS)) {
			return new ReturnBean<>(9200022 , "更新报销申请单出错！") ;
		}
		
		return new ReturnBean<>(ReturnBean.CODE_SUCCESS , "更新报销申请单成功！" ,expenseAccountRepository.save(expenseAccount)) ;
	}

	
	private String getExpenseAccountNO() {
		
		String todayStr = LocalDate.now().toString("yyyyMMdd");
        Long expenseAccountNO = expenseAccountRepository.findLastExpenseAccountNOForEveryday(todayStr + "%");
        
        if (expenseAccountNO == null || expenseAccountNO == 0) {
            todayStr += "0001" ;
        } else {
        		expenseAccountNO++;
            
            String sortNoStr = "0000" + expenseAccountNO.toString() ;
            sortNoStr.substring(sortNoStr.length()-4) ;
            todayStr = todayStr + sortNoStr ;
        }
        
        return todayStr ;
	}

	@Override
	public ReturnBean<PageWrapper<ExpenseAccount>> getMyExpenseAccount(String askUserID ,Long startTime, Long endTime, Integer pageNum, Integer pageSize) {
		
		Condition condition = new Condition();
        List<FilterCondition> filterConditions = new ArrayList<FilterCondition>();
        
    		filterConditions.add(new FilterCondition(askUserID, "askUserID", ConditionRelate.and.name(), Operation.eq.name(), 1)) ;
        
        if (null != startTime) {
        		filterConditions.add(new FilterCondition(startTime.toString(), "askTime", ConditionRelate.and.name(), Operation.ge.name(), 1)) ;
        }
        
        if (null != endTime) {
	    		filterConditions.add(new FilterCondition(endTime.toString(), "askTime", ConditionRelate.and.name(), Operation.le.name(), 1)) ;
	    }
        
        condition.setFilterCondition(filterConditions);
        
        condition = ConditionUtil.buildCondition(XiNiaoJSON.toJSONString(condition), ExpenseAccount.class).getResult();
        
        Pageable pageable = new PageRequest(pageNum - 1, pageSize, new Sort(Sort.Direction.DESC, "askTime"));
        Page<ExpenseAccount> page = expenseAccountRepository.findAll(condition.getSpecification(), pageable);
        
        transExpenseAccount(page.getContent()) ;
        
        return new ReturnBean<>(ReturnBean.CODE_SUCCESS , "获取我的报销申请单列表成功！" ,PageHelper.toPage(page)) ;
	}
	
	private List<ExpenseAccount> transExpenseAccount(List<ExpenseAccount> expenseAccounts){
		if (null==expenseAccounts || expenseAccounts.isEmpty()) {
			return null ;
		}
		
		for(ExpenseAccount expenseAccount: expenseAccounts) {
			transExpenseAccount(expenseAccount) ;
	    	}
		
		return expenseAccounts ;
	}

	@Override
	public ReturnBean<PageWrapper<ExpenseAccount>> getAllExpenseAccount(String orgID, String askUserID, Long startTime,Long endTime, Integer pageNum, Integer pageSize) {
		Condition condition = new Condition();
        List<FilterCondition> filterConditions = new ArrayList<FilterCondition>();
        
        if (null != orgID) {
	    		filterConditions.add(new FilterCondition(orgID, "orgID", ConditionRelate.and.name(), Operation.eq.name(), 1)) ;
	    }
        
        if (null != askUserID) {
	    		filterConditions.add(new FilterCondition(askUserID, "askUserID", ConditionRelate.and.name(), Operation.eq.name(), 2)) ;
	    }
        
        if (null != startTime) {
        		filterConditions.add(new FilterCondition(startTime.toString(), "askTime", ConditionRelate.and.name(), Operation.ge.name(), 3)) ;
        }
        
        if (null != endTime) {
	    		filterConditions.add(new FilterCondition(endTime.toString(), "askTime", ConditionRelate.and.name(), Operation.le.name(), 4)) ;
	    }
        
        condition.setFilterCondition(filterConditions);
        
        condition = ConditionUtil.buildCondition(XiNiaoJSON.toJSONString(condition), ExpenseAccount.class).getResult();
        
        Pageable pageable = new PageRequest(pageNum - 1, pageSize, new Sort(Sort.Direction.DESC, "askTime"));
        Page<ExpenseAccount> page = expenseAccountRepository.findAll(condition.getSpecification(), pageable);
        
        transExpenseAccount(page.getContent()) ;
        
        return new ReturnBean<>(ReturnBean.CODE_SUCCESS , "获取我的报销申请单列表成功！" ,PageHelper.toPage(page)) ;
	}

	@Override
	public ReturnBean<ExpenseAccount> getExpenseAccount(String expenseAccountID) {
		ExpenseAccount expenseAccount = expenseAccountRepository.findOne(expenseAccountID) ;
		if (null == expenseAccount) {
			return new ReturnBean<>(920001 , "报销申请单不存在！") ;
		}
		
		transExpenseAccount(expenseAccount) ;
		
		return new ReturnBean<>(ReturnBean.CODE_SUCCESS , "获取报销申请单详情成功！" ,expenseAccount) ;
	}
	
	@Override
	public ExpenseAccount transExpenseAccount(ExpenseAccount expenseAccount) {
		
		if(null != expenseAccount.getStatus()) {
			expenseAccount.setStatusStr(ExpenseAccountStatus.getName(expenseAccount.getStatus()));
		}
		
		User user = iUserService.findOne(expenseAccount.getAskUserID()) ;
		if (null != expenseAccount.getAskUserID()) {
			expenseAccount.setAskUserName(user.getName());
			expenseAccount.setAskUser(user);
		}
		
		if (null != expenseAccount.getOrgID()) {
			Organization org = iOrganizationService.findOne(expenseAccount.getOrgID()) ;
			if (null != org) {
				expenseAccount.setOrgName(org.getOrganizationName());
				expenseAccount.setAskUserOrganization(org);
			}
		}
		
		if (StringUtils.isNotEmpty(expenseAccount.getExpenseType())) {
			ExpenseType expenseType = iExpenseTypeService.findOne(expenseAccount.getExpenseType()) ;
			if (null!=expenseType) {
				expenseAccount.setExpenseTypeStr(expenseType.getExpenseTypeName());
			}
		}
		
		List<ExpenseAccountAttachment> expenseAccountAttachments = iExpenseAccountAttachmentService.findByExpenseAccountID(expenseAccount.getExpenseAccountID()) ;
		
		expenseAccount.setExpenseAccountAttachments(expenseAccountAttachments);
		
		return expenseAccount ;
	}

	@Override
	public ReturnBean<String> startWorkflow(String userId, String expenseAccountID, Map<String, Object> variables) {
		ExpenseAccount expenseAccount = expenseAccountRepository.findOne(expenseAccountID) ;
		
		if(null ==  expenseAccount) {
			return  new ReturnBean<>(9010, "提交的报销申请单不存在！");
		}
		
		User user = iUserService.findOne(userId) ;
		
		if(null ==  user) {
			return  new ReturnBean<>(9011, "报销申请人不存在！");
		}
		
		if (!user.getUserID().equals(expenseAccount.getAskUserID())) {
			return  new ReturnBean<>(9011, "当前用户不是提交的报销申请单的申请人，不能提交审核！");
		}
		
		return iExpenseAccountFlowService.startWorkflow(expenseAccountID ,userId, variables) ;
	}

	@Override
	public ReturnBean<List<ExpenseAccount>> findToDoList(String userId) {
		return new ReturnBean<>(ReturnBean.CODE_SUCCESS ,"获取报销申请单工作流待办成功！" ,iExpenseAccountFlowService.findToDoList(userId));
	}

	@Override
	public ReturnBean<String> complete(String userID, String taskID, Map<String, String[]> mapRequest) {
		return iExpenseAccountFlowService.complete(userID, taskID, mapRequest);
	}

	@Override
	public ReturnBean<ExpenseAccount> getExpenseAccountForFlow(String expenseAccountID) {
		return iExpenseAccountFlowService.getExpenseAccountForFlow(expenseAccountID);
	}

	@Override
	public ExpenseAccount findOne(String expenseAccountID) {
		return expenseAccountRepository.findOne(expenseAccountID);
	}

	@Override
	public List<ExpenseAccount> findByInProcessInsID(List<String> processInsIDs) {
		return expenseAccountRepository.findByProcessInsIDIn(processInsIDs);
	}

	@Override
	public ExpenseAccount findByProcessInsID(String processInsId) {
		return expenseAccountRepository.findByProcessInsID(processInsId);
	}

	@Override
	public ReturnBean<ExpenseAccount> save(ExpenseAccount expenseAccount) {
		return new ReturnBean<>(ReturnBean.CODE_SUCCESS ,"保存报销单成功！" ,expenseAccountRepository.save(expenseAccount));
	}

}
